home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / WaveTableStorage.c < prev    next >
Text File  |  1994-08-15  |  11KB  |  324 lines

  1. /* WaveTableStorage.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "WaveTableStorage.h"
  31. #include "Array.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34.  
  35.  
  36. struct WaveTableStorageRec
  37.     {
  38.         ArrayRec*                ListOfTables; /* of char*s or short*s */
  39.         NumBitsType            NumBits;
  40.         long                        NumFrames;
  41.     };
  42.  
  43.  
  44. /* create a new wave table storage object */
  45. WaveTableStorageRec*        NewWaveTableStorage(NumBitsType NumBits, long NumFrames)
  46.     {
  47.         WaveTableStorageRec*    Storage;
  48.  
  49.         ERROR((NumBits != eSample8bit) && (NumBits != eSample16bit),
  50.             PRERR(ForceAbort,"NewWaveTableStorage:  bad number of bits"));
  51.         ERROR((NumFrames != 2) && (NumFrames != 4) && (NumFrames != 8) && (NumFrames != 16)
  52.             && (NumFrames != 32) && (NumFrames != 64) && (NumFrames != 128)
  53.             && (NumFrames != 256) && (NumFrames != 512) && (NumFrames != 1024)
  54.             && (NumFrames != 2048) && (NumFrames != 4096) && (NumFrames != 8192)
  55.             && (NumFrames != 16384) && (NumFrames != 32768) && (NumFrames != 65536),
  56.             PRERR(ForceAbort,"NewWaveTableStorage:  bad number of frames"));
  57.         Storage = (WaveTableStorageRec*)AllocPtrCanFail(sizeof(WaveTableStorageRec),
  58.             "WaveTableStorageRec");
  59.         if (Storage == NIL)
  60.             {
  61.              FailurePoint1:
  62.                 return NIL;
  63.             }
  64.         Storage->ListOfTables = NewArray();
  65.         if (Storage->ListOfTables == NIL)
  66.             {
  67.                 ReleasePtr((char*)Storage);
  68.                 goto FailurePoint1;
  69.             }
  70.         Storage->NumBits = NumBits;
  71.         Storage->NumFrames = NumFrames;
  72.         return Storage;
  73.     }
  74.  
  75.  
  76. /* dispose of the wave table storage object */
  77. void                                        DisposeWaveTableStorage(WaveTableStorageRec* Storage)
  78.     {
  79.         long                                    Scan;
  80.         long                                    Limit;
  81.  
  82.         CheckPtrExistence(Storage);
  83.         Limit = ArrayGetLength(Storage->ListOfTables);
  84.         for (Scan = 0; Scan < Limit; Scan += 1)
  85.             {
  86.                 ReleasePtr((char*)ArrayGetElement(Storage->ListOfTables,Scan));
  87.             }
  88.         DisposeArray(Storage->ListOfTables);
  89.         ReleasePtr((char*)Storage);
  90.     }
  91.  
  92.  
  93. /* get the number of frames per table */
  94. long                                        WaveTableStorageNumFramesPerTable(WaveTableStorageRec* Storage)
  95.     {
  96.         CheckPtrExistence(Storage);
  97.         return Storage->NumFrames;
  98.     }
  99.  
  100.  
  101. /* get the number of tables */
  102. long                                        WaveTableStorageNumTables(WaveTableStorageRec* Storage)
  103.     {
  104.         CheckPtrExistence(Storage);
  105.         return ArrayGetLength(Storage->ListOfTables);
  106.     }
  107.  
  108.  
  109. /* get the number of bits for the wave table */
  110. NumBitsType                            WaveTableStorageNumBits(WaveTableStorageRec* Storage)
  111.     {
  112.         CheckPtrExistence(Storage);
  113.         return Storage->NumBits;
  114.     }
  115.  
  116.  
  117. /* get a reference to a table.  this is NOT copied, and there is no type information. */
  118. /* it is formatted as an array of characters for 8 bit data or array of shorts for */
  119. /* 16 bit data.  it contains (WaveTableStorageNumFramesPerTable + 1) elements for */
  120. /* each table.  The last element is a repeat of the first, and is provided for */
  121. /* making anti-aliasing more efficient. */
  122. void*                                        WaveTableStorageGetTable(WaveTableStorageRec* Storage,
  123.                                                     long Index)
  124.     {
  125.         CheckPtrExistence(Storage);
  126.         ERROR((Index < 0) || (Index >= ArrayGetLength(Storage->ListOfTables)),
  127.             PRERR(ForceAbort,"WaveTableStorageGetTable:  index out of range"));
  128.         return ArrayGetElement(Storage->ListOfTables,Index);
  129.     }
  130.  
  131.  
  132. /* append a new (zeroed out) table to the end of the array */
  133. MyBoolean                                WaveTableStorageAppendEntry(WaveTableStorageRec* Storage)
  134.     {
  135.         char*                                    Buffer;
  136.         long                                    Limit;
  137.         long                                    Scan;
  138.  
  139.         CheckPtrExistence(Storage);
  140.         switch (Storage->NumBits)
  141.             {
  142.                 default:
  143.                     EXECUTE(PRERR(ForceAbort,
  144.                         "WaveTableStorageAppendEntry:  internal invalid num bits"));
  145.                     break;
  146.                 case eSample8bit:
  147.                     Buffer = AllocPtrCanFail(Storage->NumFrames + 1,
  148.                         "WaveTableStorageAppendEntry");
  149.                     break;
  150.                 case eSample16bit:
  151.                     Buffer = AllocPtrCanFail(sizeof(short) * (Storage->NumFrames + 1),
  152.                         "WaveTableStorageAppendEntry");
  153.                     break;
  154.             }
  155.         if (Buffer == NIL)
  156.             {
  157.              FailurePoint1:
  158.                 return False;
  159.             }
  160.         if (!ArrayAppendElement(Storage->ListOfTables,Buffer))
  161.             {
  162.              FailurePoint2:
  163.                 ReleasePtr(Buffer);
  164.                 goto FailurePoint1;
  165.             }
  166.         Limit = PtrSize(Buffer);
  167.         for (Scan = 0; Scan < Limit; Scan += 1)
  168.             {
  169.                 Buffer[Scan] = 0;
  170.             }
  171.         return True;
  172.     }
  173.  
  174.  
  175. /* put a value into a frame in a table */
  176. void                                        WaveTableStorageSetFrame(WaveTableStorageRec* Storage,
  177.                                                     long TableIndex, long FrameIndex, largefixedsigned Value)
  178.     {
  179.         long                                    NormalizedValue;
  180.         char*                                    Reference;
  181.  
  182.         CheckPtrExistence(Storage);
  183.         ERROR((TableIndex < 0) || (TableIndex >= ArrayGetLength(Storage->ListOfTables)),
  184.             PRERR(ForceAbort,"WaveTableStorageSetFrame:  table index out of range"));
  185.         Reference = (char*)ArrayGetElement(Storage->ListOfTables,TableIndex);
  186.         ERROR((FrameIndex < 0) || (FrameIndex >= Storage->NumFrames),
  187.             PRERR(ForceAbort,"WaveTableStorageSetFrame:  frame index out of range"));
  188.         switch (Storage->NumBits)
  189.             {
  190.                 default:
  191.                     EXECUTE(PRERR(ForceAbort,
  192.                         "WaveTableStorageSetFrame:  internal invalid num bits"));
  193.                     break;
  194.                 case eSample8bit:
  195.                     NormalizedValue = roundtonearest(largefixed2double(Value) * MAX8BIT);
  196.                     if (NormalizedValue < MIN8BIT)
  197.                         {
  198.                             NormalizedValue = MIN8BIT;
  199.                         }
  200.                     else if (NormalizedValue > MAX8BIT)
  201.                         {
  202.                             NormalizedValue = MAX8BIT;
  203.                         }
  204.                     PRNGCHK(Reference,&(((char*)Reference)[FrameIndex]),sizeof(char));
  205.                     ((char*)Reference)[FrameIndex] = NormalizedValue;
  206.                     if (FrameIndex == 0)
  207.                         {
  208.                             PRNGCHK(Reference,&(((char*)Reference)[Storage->NumFrames]),
  209.                                 sizeof(char));
  210.                             ((char*)Reference)[Storage->NumFrames] = NormalizedValue;
  211.                         }
  212.                     break;
  213.                 case eSample16bit:
  214.                     NormalizedValue = roundtonearest(largefixed2double(Value) * MAX16BIT);
  215.                     if (NormalizedValue < MIN16BIT)
  216.                         {
  217.                             NormalizedValue = MIN16BIT;
  218.                         }
  219.                     else if (NormalizedValue > MAX16BIT)
  220.                         {
  221.                             NormalizedValue = MAX16BIT;
  222.                         }
  223.                     PRNGCHK(Reference,&(((short*)Reference)[FrameIndex]),sizeof(short));
  224.                     ((short*)Reference)[FrameIndex] = NormalizedValue;
  225.                     if (FrameIndex == 0)
  226.                         {
  227.                             PRNGCHK(Reference,&(((short*)Reference)[Storage->NumFrames]),
  228.                                 sizeof(short));
  229.                             ((short*)Reference)[Storage->NumFrames] = NormalizedValue;
  230.                         }
  231.                     break;
  232.             }
  233.     }
  234.  
  235.  
  236. /* get a value from a frame in a table */
  237. largefixedsigned                WaveTableStorageGetFrame(WaveTableStorageRec* Storage,
  238.                                                     long TableIndex, long FrameIndex)
  239.     {
  240.         double                                ReturnValue;
  241.         char*                                    Reference;
  242.  
  243.         CheckPtrExistence(Storage);
  244.         ERROR((TableIndex < 0) || (TableIndex >= ArrayGetLength(Storage->ListOfTables)),
  245.             PRERR(ForceAbort,"WaveTableStorageGetFrame:  table index out of range"));
  246.         Reference = (char*)ArrayGetElement(Storage->ListOfTables,TableIndex);
  247.         ERROR((FrameIndex < 0) || (FrameIndex >= Storage->NumFrames),
  248.             PRERR(ForceAbort,"WaveTableStorageGetFrame:  frame index out of range"));
  249.         switch (Storage->NumBits)
  250.             {
  251.                 default:
  252.                     EXECUTE(PRERR(ForceAbort,
  253.                         "WaveTableStorageGetFrame:  internal invalid num bits"));
  254.                     break;
  255.                 case eSample8bit:
  256.                     PRNGCHK(Reference,&(((char*)Reference)[FrameIndex]),sizeof(char));
  257.                     ReturnValue = ((double)((signed char*)Reference)[FrameIndex]) / MAX8BIT;
  258.                     break;
  259.                 case eSample16bit:
  260.                     PRNGCHK(Reference,&(((short*)Reference)[FrameIndex]),sizeof(short));
  261.                     ReturnValue = ((double)((signed short*)Reference)[FrameIndex]) / MAX16BIT;
  262.                     break;
  263.             }
  264.         return double2largefixed(ReturnValue);
  265.     }
  266.  
  267.  
  268. /* make a duplicate of the wave table */
  269. WaveTableStorageRec*        WaveTableDuplicate(WaveTableStorageRec* Original)
  270.     {
  271.         WaveTableStorageRec*    Copy;
  272.         long                                    Limit;
  273.         long                                    Scan;
  274.  
  275.         CheckPtrExistence(Original);
  276.  
  277.         Copy = (WaveTableStorageRec*)AllocPtrCanFail(sizeof(WaveTableStorageRec),
  278.             "WaveTableStorageRec");
  279.         if (Copy == NIL)
  280.             {
  281.              FailurePoint1:
  282.                 return NIL;
  283.             }
  284.         Copy->NumBits = Original->NumBits;
  285.         Copy->NumFrames = Original->NumFrames;
  286.  
  287.         Copy->ListOfTables = NewArray();
  288.         if (Copy->ListOfTables == NIL)
  289.             {
  290.              FailurePoint2:
  291.                 ReleasePtr((char*)Copy);
  292.                 goto FailurePoint1;
  293.             }
  294.  
  295.         Limit = ArrayGetLength(Original->ListOfTables);
  296.         for (Scan = 0; Scan < Limit; Scan += 1)
  297.             {
  298.                 char*                                    SliceCopy;
  299.  
  300.                 SliceCopy = CopyPtr((char*)ArrayGetElement(Original->ListOfTables,Scan));
  301.                 if (SliceCopy == NIL)
  302.                     {
  303.                         /* bummer */
  304.                      FailurePoint3:
  305.                         Limit = ArrayGetLength(Copy->ListOfTables);
  306.                         for (Scan = 0; Scan < Limit; Scan += 1)
  307.                             {
  308.                                 ReleasePtr((char*)ArrayGetElement(Copy->ListOfTables,Scan));
  309.                             }
  310.                         DisposeArray(Copy->ListOfTables);
  311.                         goto FailurePoint2;
  312.                     }
  313.                 SetTag(SliceCopy,"WaveTableStorageAppendEntry");
  314.                 if (!ArrayAppendElement(Copy->ListOfTables,SliceCopy))
  315.                     {
  316.                      FailurePoint3a:
  317.                         ReleasePtr((char*)SliceCopy);
  318.                         goto FailurePoint3;
  319.                     }
  320.             }
  321.  
  322.         return Copy;
  323.     }
  324.